
/*
 *
 * Copyright (c) 2006 P.J.Leonard
 * 
 * http://www.frinika.com
 * 
 * This file is part of Frinika.
 * 
 * Frinika is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.

 * Frinika is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.

 * You should have received a copy of the GNU General Public License
 * along with Frinika; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */
package uk.ac.bath.domains.sequence;

import uk.ac.bath.base.Fitness;
import uk.ac.bath.base.Evaluator;
import uk.ac.bath.base.Value;
import uk.ac.bath.gui.View;

/**
 *
 * @author pjl
 */
public class SequenceEvaluator extends Evaluator {

    int trialTickCount = 0;
    int max_cnt;
    int hitCount;
    Value[] prev;
    Value[] vals;
    private SequenceGenerator gen;
 //   private MachineIF machine;
    private int nIn;
    private int missCount;
    private int target;
    private int nFree;
    private int trialCount;
    private int nTrials;
    Fitness fitness;
    //  private int evalCount;

    public SequenceEvaluator(SequenceGenerator gen, int nTrials) {
        this.gen = gen;
        prev = gen.getNext();
        nIn = gen.wid;
        this.max_cnt = gen.len * 10;
        nFree = 3 * gen.len;
        target = (max_cnt - nFree - 1) * nIn;
        System.out.println(" target = " + target);
        trialCount = 0;
        this.nTrials = nTrials;
    }

    protected void initImpl() {
        trialCount=0;
        fitness=null;
    }

    private void doTick() {

        trialTickCount++;

        for (int i = 0; i < nIn; i++) {
            currentMachine.setIn(i, (float) prev[i].val);
        }

        currentMachine.tick();
        prev = gen.getNext();

    }

    @Override
    public Fitness tickImpl() {
        doTick();

        if (trialTickCount >= nFree) {
            for (int i = 0; i < nIn; i++) {
                if (prev[i].val * currentMachine.out(i) > 0.0) {
                    hitCount++;
                } else {
                    missCount++;
                }
            }
        }

        if (trialTickCount >= max_cnt) {
            fitness.addUpperBound(hitCount - missCount);
            if (trialCount >= nTrials) {
                fitness.finish();
  //              newResult(fitness, currentMachine);
            } else {
                nextTrial();
            }
        }
        return fitness;
    }

    @Override
    public View createView() {
        return new SequenceView(this);
    }

    private void nextTrial() {
        gen.reset();
        prev = gen.getNext();
        trialCount++;
        trialTickCount = 0;
    }

    public void nextEvaluationImpl() {

        hitCount = 0;
        missCount = 0;
        trialTickCount = 0;
        trialCount = 0;
        nextTrial();
        fitness = new Fitness(target,0.0f);
    }

    @Override
    public String getStatus() {
        return super.getStatus() + " " + String.format("Trial: %-4d  SubTick: %-7d", trialCount, trialTickCount);
    }

    @Override
    public String reportSetup() {
        throw new UnsupportedOperationException("Not supported yet.");
    }
}
